package cqrtplm.aop;

import cn.hutool.core.collection.CollUtil;
import com.hustcad.plm.pdm.code.model.dto.codemanagement.TyplmCodeRuleDTO;
import com.hustcad.plm.pdm.enumeration.model.dto.EnumerationInputDTO;
import com.hustcad.plm.pdm.enumeration.model.dto.EnumerationValueDTO;
import com.hustcad.plm.pdm.enumeration.model.dto.HandleEnumItemDTO;
import com.hustcad.plm.pdm.enumeration.model.vo.EnumerationItemHandleVO;
import com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationItemService;
import com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationService;
import com.ty.basic.entity.IdentifierEntity;
import cqrtplm.constant.RTErrorCodeEnum;
import cqrtplm.mapper.ProcessNumberMapper;
import cqrtplm.mapper.RTEnumMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@Aspect
@Component
@Slf4j
public class EnumerationAOP {

    @Resource
    private TyplmEnumerationItemService typlmEnumerationItemService;
    @Resource
    private TyplmEnumerationService typlmEnumerationService;
    @Resource
    private RTEnumMapper rtEnumMapper;
    @Resource
    private ProcessNumberMapper processNumberMapper;

    /**
     * 创建枚举时 校验显示名称不可重复
     */
    @SneakyThrows
    @Around(value = "execution(* com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationService.handleEnumItemList(..))")
    public Object checkWhenCreateEnum(ProceedingJoinPoint point) {
        Object[] args = point.getArgs();
        HandleEnumItemDTO dto = (HandleEnumItemDTO)args[0];
        List<EnumerationItemHandleVO> enumItemList = dto.getEnumItemList();
        if(CollUtil.isNotEmpty(enumItemList)){
            List<String> enmuDiaNameList = enumItemList.stream().map(EnumerationItemHandleVO::getDisplayName)
                    .filter(Objects::nonNull)
                    .collect(
                    Collectors.toList());
            Set<String> uniqueNames = new HashSet<>();
            Set<String> duplicateNames = enmuDiaNameList.stream()
                    .filter(name -> !uniqueNames.add(name))
                    .collect(Collectors.toSet());
            if (!duplicateNames.isEmpty()) {
                String errorMsg = "存在重复的枚举值名称: " + String.join("、", duplicateNames);
                throw RTErrorCodeEnum.ENUM_VALUE_NOT_EXIST.getException(errorMsg);
            }
            for (EnumerationItemHandleVO enumerationItemHandleVO : enumItemList) {
                if(StringUtils.isEmpty(enumerationItemHandleVO.getName())||StringUtils.isEmpty(enumerationItemHandleVO.getInternalName())||StringUtils.isBlank(enumerationItemHandleVO.getName())){
                    enumerationItemHandleVO.setName(enumerationItemHandleVO.getDisplayName());
                    enumerationItemHandleVO.setInternalName(enumerationItemHandleVO.getDisplayName());
                }
            }
        }
        return point.proceed();
    }


    @SneakyThrows
    @Around(value = "execution(* com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationService.createEnumDef(..))")
    public Object createEnumDefAop(ProceedingJoinPoint point) {
        Object[] args = point.getArgs();
        EnumerationInputDTO dto = (EnumerationInputDTO) args[0];
        if(StringUtils.isBlank(dto.getName())||StringUtils.isEmpty(dto.getName())){
            dto.setName(processNumberMapper.generateEnumDefCode());
        }
        return point.proceed();
    }

    @SneakyThrows
    @Around(value = "execution(* com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationService.getEnumerationDefList(..))")
    public Object getEnumerationDefList(ProceedingJoinPoint point) {
        List<EnumerationValueDTO> list = (List<EnumerationValueDTO>) point.proceed();
        Iterator<EnumerationValueDTO> iterator = list.iterator();
        BigInteger enumGroupId = rtEnumMapper.selectEnumGroupId("Attribute Card Enums");
        if(enumGroupId != null){
            while (iterator.hasNext()) {
                EnumerationValueDTO typlmCodeRuleDTO = iterator.next();
                BigInteger pId = typlmCodeRuleDTO.getPid();
                if (enumGroupId.equals(pId)) {
                    iterator.remove();
                }
            }
        }
        return list;
    }

    @Before( value = "execution(* com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationService.deleteEnumDef(..))")
    public void createFlowCode(JoinPoint point) {
        Object[] args = point.getArgs();
        IdentifierEntity enumerationEntity =(IdentifierEntity)args[0];
        List<String> names= rtEnumMapper.selectEnumUsageByOid(enumerationEntity.getOid().toString());
        if(CollUtil.isNotEmpty(names)){
            throw RTErrorCodeEnum.CLASSIFICATION_TYPE_ERROR.getException("枚举被以下卡片使用"+String.join(",", names)+"，无法删除！");
        }
    }
    /**
     * 添加枚举值时进行验证
     * @param point
     * @return
     */
//    @SneakyThrows
//    @Around(value = "execution(* com.hustcad.plm.pdm.enumeration.service.impl.TyplmEnumerationServiceImpl.handleEnumItemList(..))")
//    public Object checkWhenCreateChangeRequest(ProceedingJoinPoint point){
//        log.info("========切面开始========");
//
//        // 提取变动的枚举值名称列表
//        Object[] args = point.getArgs();
//        HandleEnumItemDTO dto = (HandleEnumItemDTO) args[0];
//
//        // 查询当前枚举类并提取根类名称 suffix
//        String rootEnumName = getRootNameFromCurrentEnum(dto.getDefoid());
//        log.info("枚举根类名称: {}", rootEnumName);
//        // 如果 rootEnumName 为 null，说明不包含 '_'，无需后续校验，直接放行
//        if (rootEnumName == null) {
//            return point.proceed();
//        }
//
//        List<String> newNames = extractNewNames(dto);
//        log.info("枚举值变动的name列表: {}", newNames);
//
//
//        // 查询根类的所有合法枚举值
//        List<String> validNames = queryValidNamesByRootName(rootEnumName);
//        log.info("合法枚举值列表: {}", validNames);
//
//        // 校验是否所有新增项都存在于合法列表中
//        List<String> missingItems = findMissingItems(newNames, validNames);
//        if (!missingItems.isEmpty()) {
//            String errorMsg = String.format("录入失败 %s库中不含枚举值【%s】如需添加请先维护相关枚举值。", getAllValidNames(dto.getDefoid()), String.join("、", missingItems));
//            throw NOT_FOUND_FILE_TEMPLATE.getException(errorMsg);
//        }
//
//        return point.proceed();
//    }
//
//    /**
//     * 提取变动的枚举值名称
//     */
//    private List<String> extractNewNames(HandleEnumItemDTO dto) {
//        return Optional.ofNullable(dto.getEnumItemList())
//                .orElse(Collections.emptyList()).stream()
//                .map(EnumerationItemHandleVO::getName)
//                .filter(name -> name != null && !name.isEmpty())
//                .collect(Collectors.toList());
//    }
//
//    /**
//     * 查询当前枚举类并提取 root 名称
//     * 如果 fullName 不含 '_', 则返回 null 表示无需后续校验
//     */
//    private String getRootNameFromCurrentEnum(BigInteger defoid) {
//        TyEnumerationdefDO tyEnumerationdefDO = tyEnumerationdefService.selectByOid(defoid);
//        String fullName = tyEnumerationdefDO.getName();
//        if (fullName.contains("_")) {
//            return fullName.substring(fullName.lastIndexOf("_") + 1);
//        } else {
//            return null; // 表示不需后续处理
//        }
//    }
//
//    private String getAllValidNames(BigInteger defoid) {
//        return tyEnumerationdefService.selectDisplayNameByOid(defoid);
//
//    }
//
//    /**
//     * 查询根类下的所有合法枚举值
//     */
//    private List<String> queryValidNamesByRootName(String rootName) {
//        EnumerationQueryVO queryVO = new EnumerationQueryVO();
//        queryVO.setSystem(0);
//
//        List<EnumerationValueDTO> tree = typlmEnumerationService.getEnumerationTreeNew(queryVO);
//        return tree.stream()
//                .filter(dto -> rootName.equals(dto.getName()))
//                .findFirst()
//                .map(rootDto -> {
//                    IdentifierEntity identifier = new IdentifierEntity();
//                    identifier.setOid(rootDto.getOid());
//
//                    List<EnumerationItemHandleVO> items = typlmEnumerationItemService.queryEnumerationItemByDefOid(identifier);
//                    return items.stream()
//                            .map(EnumerationItemHandleVO::getName)
//                            .filter(name -> name != null && !name.isEmpty())
//                            .collect(Collectors.toList());
//                })
//                .orElseThrow(() -> new IllegalArgumentException("未找到对应的根枚举定义"));
//    }
    @SneakyThrows
    @Around(value = "execution(* com.hustcad.plm.pdm.code.service.codemanagement.TyplmCodeRuleService.batchCreateCodeRule(..))" )
    public Object createFlowCode(ProceedingJoinPoint point) {
        Object[] args = point.getArgs();
        List<TyplmCodeRuleDTO> dto = (List<TyplmCodeRuleDTO>) args[0];
        for (TyplmCodeRuleDTO typlmCodeRuleDTO : dto) {
            if (StringUtils.isEmpty(typlmCodeRuleDTO.getObjectNumber())) {
                typlmCodeRuleDTO.setObjectNumber(processNumberMapper.generateFlowCodeNumber());
            }
        }

        return point.proceed();

    }
    /**
     * 找出不在合法列表中的项
     */
    private List<String> findMissingItems(List<String> newNames, List<String> validNames) {
        return newNames.stream()
                .filter(name -> !validNames.contains(name))
                .collect(Collectors.toList());
    }
}
